#include "../pch.h"
#include "REFEncoding.h"
#include "REFUTF8Encoding.h"
#include "CharUnicodeInfo.h"


namespace BFX
{

#define	FASTLOOP	1

typedef	signed char	SBYTE;

// These are bitmasks used to maintain the state in the decoder. They occupy the higher bits
// while the actual character is being built in the lower bits. They are shifted together
// with the actual bits of the character.

// bits 30 & 31 are used for pending bits fixup
#define	FINAL_BYTE			(int)(1 << 29)
#define	SUPPLIMENTARY_SEQ	(int)(1 << 28)
#define	THREE_BYTE_SEQ		(int)(1 << 27)

#define	CHAR_IN_RANGE(ch, start, end)	\
	((UINT)(ch - start) <= (UINT)(end - start))

// diffs two char pointers using unsigned arithmetic. The unsigned arithmetic
// is good enough for us, and it tends to generate better code than the signed
// arithmetic generated by default
#define WCHAR_PTR_DIFF(a, b)	\
	((int)(((UINT)((BYTE*)a - (BYTE*)b)) >> 1))

// byte* flavor just for parity
#define	BYTE_PTR_DIFF(a, b)	\
	((int)(a - b))

////////////////////////////////////////////////////////////////////////////////

REFUTF8Encoding::REFUTF8Encoding() :
		REFEncoding(CodePageUTF8)
{
}

REFUTF8Encoding::~REFUTF8Encoding()
{
}

// Our workhorse
// Note:  We ignore mismatched surrogates, unless the exception flag is set in which case we throw
int REFUTF8Encoding::GetMaxByteCount(int nCharCount) const
{
	BFX_REQUIRE1(nCharCount >= 0, "Non-negative number required.");

	// Characters would be # of characters + 1 in case left over high surrogate is ? * max fallback
	long long lByteCount = (long long)nCharCount + 1;

	// Max 3 bytes per char.  (4 bytes per 2 chars for surrogates)
	lByteCount *= 3;

	BFX_ENSURE1(lByteCount <= 0x7fffffff, "Too many characters. The resulting number of bytes is larger than what can be returned as an int.");

	return (int)lByteCount;
}

// Calculates the maximum number of characters produced by decoding the specified number of bytes.
int REFUTF8Encoding::GetMaxCharCount(int nByteCount) const
{
	BFX_REQUIRE1(nByteCount >= 0, "Non-negative number required.");

	// Figure out our length, 1 char per input byte + 1 char if 1st byte is last byte of 4 byte surrogate pair
	long long lCharCount = ((long long)nByteCount + 1);

	BFX_ENSURE1(lCharCount <= 0x7fffffff, "Too many characters. The resulting number of bytes is larger than what can be returned as an int.");

	return (int)lCharCount;
}

// Calculates the number of characters produced by decoding a sequence of bytes.
int REFUTF8Encoding::GetCharCount(const BYTE* pBytes, int nCount, REFDecoder* pDecoder) const
{
	// Validate the parameters.
	BFX_REQUIRE1 (pBytes != NULL, "Null pointer disallowed");
	BFX_REQUIRE1 (nCount >= 0, "Non-negative number required.");

	BFX_ASSERT(nCount >=0);
	BFX_ASSERT(pBytes!=NULL);

	// Initialize stuff
	const BYTE *pSrc = pBytes;
	const BYTE *pEnd = pSrc+nCount;

	// Start by assuming we have as many as count, nCharCount always includes the adjustment
	// for the character being decoded
	int nCharCount = nCount;
	int ch = 0;
	REF<REFDecoderFallbackBuffer> pFallback;

	if (pDecoder != NULL)
	{
		UTF8Decoder* pUtf8Decoder = (UTF8Decoder*)pDecoder;
		ch = pUtf8Decoder->m_bits;
		nCharCount -= (ch >> 30);	// Adjust char count for # of expected bytes and expected output chars.

		// Shouldn't have anything in fallback buffer for GetCharCount
		BFX_ASSERT1(!pUtf8Decoder->HasFallbackBuffer() || pUtf8Decoder->GetFallbackBuffer()->GetRemaining() == 0, "Expected empty fallback buffer at start");
	}

	for (;;)
	{
		int cha;
		// SLOWLOOP: does all range checks, handles all special cases, but it is slow

		if (pSrc >= pEnd)
		{
			break;
		}

		if (ch == 0)
		{
			// no pending bits
			goto ReadChar;
		}

		// read next byte. The JIT optimization seems to be getting confused when
		// compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
		cha = *pSrc;
		pSrc++;

		// we are expecting to see trailing bytes like 10vvvvvv
		if ((cha & ((SBYTE)0xC0)) != 0x80)
		{
			// This can be a valid starting byte for another UTF8 byte sequence, so let's put
			// the current byte back, and try to see if this is a valid byte for another UTF8 byte sequence
			pSrc--;
			nCharCount += (ch >> 30);
			goto InvalidByteSequence;
		}

		// fold in the new byte
		ch = (ch << 6) | (cha & 0x3F);

		if ((ch & FINAL_BYTE) == 0)
		{
			BFX_ASSERT( (ch & (SUPPLIMENTARY_SEQ | THREE_BYTE_SEQ)) != 0);	// Invariant volation

			if ((ch & SUPPLIMENTARY_SEQ) != 0)
			{
				if ((ch & (FINAL_BYTE >> 6)) != 0)
				{
					// this is 3rd byte (of 4 byte supplimentary) - nothing to do
					continue;
				}

				// 2nd byte, check for non-shortest form of supplimentary char and the valid
				// supplimentary characters in range 0x010000 - 0x10FFFF at the same time
				if (!CHAR_IN_RANGE((ch & 0x1F0), 0x10, 0x100))
				{
					goto InvalidByteSequence;
				}
			}
			else
			{
				// Must be 2nd byte of a 3-byte sequence
				// check for non-shortest form of 3 byte seq
				if ((ch & (0x1F << 5)) == 0 ||                  // non-shortest form
					(ch & (0xF800 >> 6) ) == (0xD800 >> 6))     // illegal individually encoded surrogate
				{
					goto InvalidByteSequence;
				}
			}
			continue;
		}

		// ready to punch

		// adjust for surrogates in non-shortest form
		if ((ch & (SUPPLIMENTARY_SEQ | 0x1F0000)) == SUPPLIMENTARY_SEQ)
		{
			nCharCount--;
		}
		goto EncodeChar;

InvalidByteSequence:
		// this code fragment should be close to the gotos referencing it
		// Have to do fallback for invalid bytes
		if (pFallback == NULL)
		{
			if (pDecoder == NULL)
				pFallback = m_pDecoderFallback->CreateFallbackBuffer();
			else
				pFallback = pDecoder->GetFallbackBuffer();
			pFallback->Initialize(pBytes, NULL);
		}
		nCharCount += FallbackInvalidByteSequence(pSrc, ch, pFallback);

		ch = 0;
		continue;

ReadChar:
		ch = *pSrc;
		pSrc++;

ProcessChar:
		if (ch > 0x7F)
		{
			// If its > 0x7F, its start of a new multi-byte sequence

			// Long sequence, so unreserve our char.
			nCharCount--;

			// bit 6 has to be non-zero for start of multibyte chars.
			if ((ch & 0x40) == 0)
			{
				// Unexpected trail byte
				goto InvalidByteSequence;
			}

			// start a new long code
			if ((ch & 0x20) != 0)
			{
				if ((ch & 0x10) != 0)
				{
					// 4 byte encoding - supplimentary character (2 surrogates)

					ch &= 0x0F;

					// check that bit 4 is zero and the valid supplimentary character
					// range 0x000000 - 0x10FFFF at the same time
					if (ch > 0x04)
					{
						ch |= 0xf0;
						goto InvalidByteSequence;
					}

					// Add bit flags so that when we check new characters & rotate we'll be flagged correctly.
					// Final byte flag, count fix if we don't make final byte & supplimentary sequence flag.
					ch |= (FINAL_BYTE >> 3*6) |  // Final byte is 3 more bytes from now
						(1 << 30) |           // If it dies on next byte we'll need an extra char
						(3 << (30-2*6)) |     // If it dies on last byte we'll need to subtract a char
						(SUPPLIMENTARY_SEQ) | (SUPPLIMENTARY_SEQ >> 6) |
						(SUPPLIMENTARY_SEQ >> 2*6) | (SUPPLIMENTARY_SEQ >> 3*6);

					// Our character count will be 2 characters for these 4 bytes, so subtract another char
					nCharCount--;
				}
				else
				{
					// 3 byte encoding
					// Add bit flags so that when we check new characters & rotate we'll be flagged correctly.
					ch = (ch & 0x0F) | ( (FINAL_BYTE >> 2*6) | (1 << 30) |
						(THREE_BYTE_SEQ) | (THREE_BYTE_SEQ >> 6) | (THREE_BYTE_SEQ >> 2*6) );

					// We'll expect 1 character for these 3 bytes, so subtract another char.
					nCharCount--;
				}
			}
			else
			{
				// 2 byte encoding

				ch &= 0x1F;

				// check for non-shortest form
				if (ch <= 1)
				{
					ch |= 0xc0;
					goto InvalidByteSequence;
				}

				// Add bit flags so we'll be flagged correctly
				ch |= (FINAL_BYTE >> 6);
			}
			continue;
		}

EncodeChar:

#ifdef FASTLOOP
		int nAvailableBytes = BYTE_PTR_DIFF(pEnd, pSrc);

		// don't fall into the fast decoding loop if we don't have enough bytes
		if (nAvailableBytes <= 13)
		{
			// try to get over the remainder of the ascii characters fast though
			const BYTE* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered
			while (pSrc < pLocalEnd)
			{
				ch = *pSrc;
				pSrc++;

				if (ch > 0x7F)
					goto ProcessChar;
			}
			// we are done
			ch = 0;
			break;
		}

		// To compute the upper bound, assume that all characters are ASCII characters at this point,
		//  the boundary will be decreased for every non-ASCII character we encounter
		// Also, we need 7 chars reserve for the unrolled ansi decoding loop and for decoding of multibyte sequences
		const BYTE *pStop = pSrc + nAvailableBytes - 7;

		while (pSrc < pStop)
		{
			ch = *pSrc;
			pSrc++;

			if (ch > 0x7F)
			{
				goto LongCode;
			}

			// get pSrc 2-byte aligned
			if ((((long)pSrc) & 0x1) != 0)
			{
				ch = *pSrc;
				pSrc++;
				if (ch > 0x7F)
				{
					goto LongCode;
				}
			}

			// get pSrc 4-byte aligned
			if ((((long)pSrc) & 0x2) != 0)
			{
				ch = *(UINT16*)pSrc;
				if ((ch & 0x8080) != 0)
				{
					goto LongCodeWithMask16;
				}
				pSrc += 2;
			}

			// Run 8 + 8 characters at a time!
			while (pSrc < pStop)
			{
				ch = *(int*)pSrc;
				int chb = *(int*)(pSrc+4);
				if (((ch | chb) & ((int)0x80808080)) != 0)
				{
					goto LongCodeWithMask32;
				}
				pSrc += 8;

				// This is a really small loop - unroll it
				if (pSrc >= pStop)
					break;

				ch = *(int*)pSrc;
				chb = *(int*)(pSrc+4);
				if (((ch | chb) & ((int)0x80808080)) != 0)
				{
					goto LongCodeWithMask32;
				}
				pSrc += 8;
			}
			break;

#ifdef BIGENDIAN
LongCodeWithMask32:
			// be careful about the sign extension
			ch = (int)(((UINT)ch) >> 16);
LongCodeWithMask16:
			ch = (int)(((UINT)ch) >> 8);
#else // BIGENDIAN
LongCodeWithMask32:
LongCodeWithMask16:
			ch &= 0xFF;
#endif // BIGENDIAN
			pSrc++;
			if (ch <= 0x7F)
			{
				continue;
			}

LongCode:
			int chc = *pSrc;
			pSrc++;

			if (
				// bit 6 has to be zero
				(ch & 0x40) == 0 ||
				// we are expecting to see trailing bytes like 10vvvvvv
				(chc & ((SBYTE)0xC0)) != 0x80)
			{
				goto BadLongCode;
			}

			chc &= 0x3F;

			// start a new long code
			if ((ch & 0x20) != 0)
			{

				// fold the first two bytes together
				chc |= (ch & 0x0F) << 6;

				if ((ch & 0x10) != 0)
				{
					// 4 byte encoding - surrogate
					ch = *pSrc;
					if (
						// check that bit 4 is zero, the non-shortest form of surrogate
						// and the valid surrogate range 0x000000 - 0x10FFFF at the same time
						!CHAR_IN_RANGE((chc >> 4), 0x01, 0x10) ||
						// we are expecting to see trailing bytes like 10vvvvvv
						(ch & ((SBYTE)0xC0)) != 0x80 )
					{
						goto BadLongCode;
					}

					chc = (chc << 6) | (ch & 0x3F);

					ch = *(pSrc+1);
					// we are expecting to see trailing bytes like 10vvvvvv
					if ((ch & ((SBYTE)0xC0)) != 0x80)
					{
						goto BadLongCode;
					}
					pSrc += 2;

					// extra byte
					nCharCount--;
				}
				else {
					// 3 byte encoding
					ch = *pSrc;
					if (
						// check for non-shortest form of 3 byte seq
						(chc & (0x1F << 5)) == 0 ||
						// Can't have surrogates here.
						(chc & (0xF800 >> 6) ) == (0xD800 >> 6) ||
						// we are expecting to see trailing bytes like 10vvvvvv
						(ch & ((SBYTE)0xC0)) != 0x80 )
					{
						goto BadLongCode;
					}
					pSrc++;

					// extra byte
					nCharCount--;
				}
			}
			else
			{
				// 2 byte encoding

				// check for non-shortest form
				if ((ch & 0x1E) == 0)
				{
					goto BadLongCode;
				}
			}

			// extra byte
			nCharCount--;
		}
#endif // FASTLOOP

		// no pending bits at this point
		ch = 0;
		continue;

BadLongCode:
		pSrc -= 2;
		ch = 0;
		continue;
	}

	// May have a problem if we have to flush
	if (ch != 0)
	{
		// We were already adjusting for these, so need to unadjust
		nCharCount += (ch >> 30);
		if (pDecoder == NULL || pDecoder->IsFlushRequired())
		{
			// Have to do fallback for invalid bytes
			if (pFallback == NULL)
			{
				if (pDecoder == NULL)
					pFallback = m_pDecoderFallback->CreateFallbackBuffer();
				else
					pFallback = pDecoder->GetFallbackBuffer();
				pFallback->Initialize(pBytes, NULL);
			}
			nCharCount += FallbackInvalidByteSequence(pSrc, ch, pFallback);
		}
	}

	// Shouldn't have anything in fallback buffer for GetCharCount
	// (don't have to check m_bThrowOnOverflow for count)
	// BFX_ASSERT(pFallback == NULL || pFallback->GetRemaining() == 0);	// Expected empty fallback buffer at end");

	return nCharCount;
}

int REFUTF8Encoding::GetChars(const BYTE* pBytes, int nByteCount, OUT UCHAR* pChars, int nCharCount, REFDecoder* pDecoder) const
{
	// Validate the parameters.
	BFX_REQUIRE(pChars != NULL && pBytes != NULL && "Null pointer is disallowed.");
	BFX_REQUIRE(nCharCount >= 0 && nByteCount >= 0 && "Non-negative number required.");

	const BYTE *pSrc = pBytes;
	UCHAR *pTarget = pChars;

	const BYTE *pEnd = pSrc+nByteCount;
	UCHAR *pAllocatedBufferEnd = pTarget + nCharCount;

	int ch = 0;
	REF<REFDecoderFallbackBuffer> pFallback = NULL;

	if (pDecoder != NULL)
	{
		UTF8Decoder* pUtf8Decoder = (UTF8Decoder*)pDecoder;
		ch = pUtf8Decoder->m_bits;

		// Shouldn't have anything in fallback buffer for GetChars
		BFX_ASSERT1(!pUtf8Decoder->HasFallbackBuffer() || pUtf8Decoder->GetFallbackBuffer()->GetRemaining() == 0, "Expected empty fallback buffer at start");
	}

	for (;;)
	{
		int cha;
		// SLOWLOOP: does all range checks, handles all special cases, but it is slow

		if (pSrc >= pEnd)
		{
			break;
		}

		if (ch == 0)
		{
			// no pending bits
			goto ReadChar;
		}

		// read next byte. The JIT optimization seems to be getting confused when
		// compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
		cha = *pSrc;
		pSrc++;

		// we are expecting to see trailing bytes like 10vvvvvv
		if ((cha & ((SBYTE)0xC0)) != 0x80)
		{
			// This can be a valid starting byte for another UTF8 byte sequence, so let's put
			// the current byte back, and try to see if this is a valid byte for another UTF8 byte sequence
			pSrc--;
			goto InvalidByteSequence;
		}

		// fold in the new byte
		ch = (ch << 6) | (cha & 0x3F);

		if ((ch & FINAL_BYTE) == 0)
		{
			// Not at last byte yet
			BFX_ASSERT( (ch & (SUPPLIMENTARY_SEQ | THREE_BYTE_SEQ)) != 0);	// Invariant volation

			if ((ch & SUPPLIMENTARY_SEQ) != 0)
			{
				// Its a 4-byte supplimentary sequence
				if ((ch & (FINAL_BYTE >> 6)) != 0)
				{
					// this is 3rd byte of 4 byte sequence - nothing to do
					continue;
				}

				// 2nd byte of 4 bytes
				// check for non-shortest form of surrogate and the valid surrogate
				// range 0x000000 - 0x10FFFF at the same time
				if (!CHAR_IN_RANGE((ch & 0x1F0), 0x10, 0x100))
				{
					goto InvalidByteSequence;
				}
			}
			else
			{
				// Must be 2nd byte of a 3-byte sequence
				// check for non-shortest form of 3 byte seq
				if ((ch & (0x1F << 5)) == 0 ||                  // non-shortest form
					(ch & (0xF800 >> 6) ) == (0xD800 >> 6))     // illegal individually encoded surrogate
				{
					goto InvalidByteSequence;
				}
			}
			continue;
		}

		// ready to punch

		// adjust for surrogates in non-shortest form
		if ((ch & (SUPPLIMENTARY_SEQ | 0x1F0000)) == SUPPLIMENTARY_SEQ)
		{
			nCharCount--;
		}
		goto EncodeChar;

InvalidByteSequence:
		// this code fragment should be close to the gotos referencing it
		// Have to do fallback for invalid bytes
		if (pFallback == NULL)
		{
			if (pDecoder == NULL)
				pFallback = m_pDecoderFallback->CreateFallbackBuffer();
			else
				pFallback = pDecoder->GetFallbackBuffer();
			pFallback->Initialize(pBytes, pAllocatedBufferEnd);
		}
		// This'll back us up the appropriate # of bytes if we didn't get anywhere
		if (!FallbackInvalidByteSequence(INOUT pSrc, ch, pFallback, INOUT pTarget))
		{
			// Ran out of buffer space
			BFX_ASSERT1(pSrc >= pBytes || pTarget == pChars, "Expected to throw or remain in byte buffer after fallback");
			pFallback->ResetAll();
			BFX_ENSURE1(false, "The output char buffer is too small to contain the decoded characters.");
			ch = 0;
			break;
		}

		BFX_ASSERT1(pSrc >= pBytes, "Expected invalid byte sequence to have remained within the byte array");
		ch = 0;
		continue;

ReadChar:
		ch = *pSrc;
		pSrc++;

ProcessChar:
		if (ch > 0x7F)
		{
			// If its > 0x7F, its start of a new multi-byte sequence

			// Long sequence, so unreserve our char.
			nCharCount--;

			// bit 6 has to be non-zero for start of multibyte chars.
			if ((ch & 0x40) == 0)
			{
				// Unexpected trail byte
				goto InvalidByteSequence;
			}

			// start a new long code
			if ((ch & 0x20) != 0)
			{
				if ((ch & 0x10) != 0)
				{
					// 4 byte encoding - supplimentary character (2 surrogates)

					ch &= 0x0F;

					// check that bit 4 is zero and the valid supplimentary character
					// range 0x000000 - 0x10FFFF at the same time
					if (ch > 0x04)
					{
						ch |= 0xf0;
						goto InvalidByteSequence;
					}

					// Add bit flags so that when we check new characters & rotate we'll be flagged correctly.
					// Final byte flag, count fix if we don't make final byte & supplimentary sequence flag.
					ch |= (FINAL_BYTE >> 3*6) |  // Final byte is 3 more bytes from now
						(1 << 30) |           // If it dies on next byte we'll need an extra char
						(3 << (30-2*6)) |     // If it dies on last byte we'll need to subtract a char
						(SUPPLIMENTARY_SEQ) | (SUPPLIMENTARY_SEQ >> 6) |
						(SUPPLIMENTARY_SEQ >> 2*6) | (SUPPLIMENTARY_SEQ >> 3*6);

					// Our character count will be 2 characters for these 4 bytes, so subtract another char
					nCharCount--;
				}
				else
				{
					// 3 byte encoding
					// Add bit flags so that when we check new characters & rotate we'll be flagged correctly.
					ch = (ch & 0x0F) | ( (FINAL_BYTE >> 2*6) | (1 << 30) |
						(THREE_BYTE_SEQ) | (THREE_BYTE_SEQ >> 6) | (THREE_BYTE_SEQ >> 2*6) );

					// We'll expect 1 character for these 3 bytes, so subtract another char.
					nCharCount--;
				}
			}
			else
			{
				// 2 byte encoding

				ch &= 0x1F;

				// check for non-shortest form
				if (ch <= 1)
				{
					ch |= 0xc0;
					goto InvalidByteSequence;
				}

				// Add bit flags so we'll be flagged correctly
				ch |= (FINAL_BYTE >> 6);
			}
			continue;
		}

EncodeChar:
		// write the pending character
		if (pTarget >= pAllocatedBufferEnd)
		{
			// Fix chars so we make sure to throw if we didn't output anything
			ch &= 0x1fffff;
			if (ch > 0x7f)
			{
				if (ch > 0x7ff)
				{
					if (ch >= CharUnicodeInfo::W_LOW_SURROGATE_START &&
						ch <= CharUnicodeInfo::W_LOW_SURROGATE_END)
					{
						pSrc--;     // It was 4 bytes
						pTarget--;  // 1 was stored already, but we can't remember 1/2, so back up
					}
					else if (ch > 0xffff)
					{
						pSrc--;     // It was 4 bytes, nothing was stored
					}
					pSrc--;         // It was at least 3 bytes
				}
				pSrc--;             // It was at least 2 bytes
			}
			pSrc--;

			// Throw that we don't have enough room (pSrc could be < chars if we had started to process
			// a 4 byte sequence alredy)
			BFX_ASSERT(pSrc >= pBytes || pTarget == pChars);
			BFX_ENSURE1(false, "Chars buffer overflow");

			// Don't store ch in decoder, we already backed up to its start
			ch = 0;

			// Didn't throw, just use this buffer size.
			break;
		}
		*pTarget = (UCHAR)ch;
		pTarget++;

#ifdef FASTLOOP
		int nAvailableChars = WCHAR_PTR_DIFF(pAllocatedBufferEnd, pTarget);
		int nAvailableBytes = BYTE_PTR_DIFF(pEnd, pSrc);

		// don't fall into the fast decoding loop if we don't have enough bytes
		// Test for nAvailableChars is done because pStop would be <= pTarget.
		if (nAvailableBytes <= 13)
		{
			// we may need as many as 1 character per byte
			if (nAvailableChars < nAvailableBytes)
			{
				// not enough output room.  no pending bits at this point
				ch = 0;
				continue;
			}

			// try to get over the remainder of the ascii characters fast though
			const BYTE* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered
			while (pSrc < pLocalEnd)
			{
				ch = *pSrc;
				pSrc++;

				if (ch > 0x7F)
					goto ProcessChar;

				*pTarget = (UCHAR)ch;
				pTarget++;
			}
			// we are done
			ch = 0;
			break;
		}

		// we may need as many as 1 character per byte, so reduce the byte count if necessary.
		// If nAvailableChars is too small, pStop will be before pTarget and we won't do fast loop.
		if (nAvailableChars < nAvailableBytes)
		{
			nAvailableBytes = nAvailableChars;
		}

		// To compute the upper bound, assume that all characters are ASCII characters at this point,
		//  the boundary will be decreased for every non-ASCII character we encounter
		// Also, we need 7 chars reserve for the unrolled ansi decoding loop and for decoding of multibyte sequences
		UCHAR *pStop = pTarget + nAvailableBytes - 7;

		while (pTarget < pStop)
		{
			ch = *pSrc;
			pSrc++;

			if (ch > 0x7F)
			{
				goto LongCode;
			}
			*pTarget = (UCHAR)ch;
			pTarget++;

			// get pSrc to be 2-byte aligned
			if ((((long)pSrc) & 0x1) != 0)
			{
				ch = *pSrc;
				pSrc++;
				if (ch > 0x7F)
				{
					goto LongCode;
				}
				*pTarget = (UCHAR)ch;
				pTarget++;
			}

			// get pSrc to be 4-byte aligned
			if ((((long)pSrc) & 0x2) != 0)
			{
				ch = *(UINT16*)pSrc;
				if ((ch & 0x8080) != 0)
				{
					goto LongCodeWithMask16;
				}

#ifdef BIGENDIAN
				*pTarget = (UCHAR)((ch >> 8) & 0x7F);
				pSrc += 2;
				*(pTarget+1) = (UCHAR)(ch & 0x7F);
				pTarget += 2;
#else // BIGENDIAN
				*pTarget = (UCHAR)(ch & 0x7F);
				pSrc += 2;
				*(pTarget+1) = (UCHAR)((ch >> 8) & 0x7F);
				pTarget += 2;
#endif // BIGENDIAN
			}

			// Run 8 characters at a time!
			while (pTarget < pStop)
			{
				ch = *(int*)pSrc;
				int chb = *(int*)(pSrc+4);
				if (((ch | chb) & ((int)0x80808080)) != 0)
				{
					goto LongCodeWithMask32;
				}

#ifdef BIGENDIAN
				*pTarget = (UCHAR)((ch >> 24) & 0x7F);
				*(pTarget+1) = (UCHAR)((ch >> 16) & 0x7F);
				*(pTarget+2) = (UCHAR)((ch >> 8) & 0x7F);
				*(pTarget+3) = (UCHAR)(ch & 0x7F);
				pSrc += 8;
				*(pTarget+4) = (UCHAR)((chb >> 24) & 0x7F);
				*(pTarget+5) = (UCHAR)((chb >> 16) & 0x7F);
				*(pTarget+6) = (UCHAR)((chb >> 8) & 0x7F);
				*(pTarget+7) = (UCHAR)(chb & 0x7F);
				pTarget += 8;
#else // BIGENDIAN
				*pTarget = (UCHAR)(ch & 0x7F);
				*(pTarget+1) = (UCHAR)((ch >> 8) & 0x7F);
				*(pTarget+2) = (UCHAR)((ch >> 16) & 0x7F);
				*(pTarget+3) = (UCHAR)((ch >> 24) & 0x7F);
				pSrc += 8;
				*(pTarget+4) = (UCHAR)(chb & 0x7F);
				*(pTarget+5) = (UCHAR)((chb >> 8) & 0x7F);
				*(pTarget+6) = (UCHAR)((chb >> 16) & 0x7F);
				*(pTarget+7) = (UCHAR)((chb >> 24) & 0x7F);
				pTarget += 8;
#endif // BIGENDIAN
			}
			break;

#ifdef BIGENDIAN
LongCodeWithMask32:
			// be careful about the sign extension
			ch = (int)(((UINT)ch) >> 16);
LongCodeWithMask16:
			ch = (int)(((UINT)ch) >> 8);
#else // BIGENDIAN
LongCodeWithMask32:
LongCodeWithMask16:
			ch &= 0xFF;
#endif // BIGENDIAN
			pSrc++;
			if (ch <= 0x7F)
			{
				*pTarget = (UCHAR)ch;
				pTarget++;
				continue;
			}

LongCode:
			int chc = *pSrc;
			pSrc++;

			if (
				// bit 6 has to be zero
				(ch & 0x40) == 0 ||
				// we are expecting to see trailing bytes like 10vvvvvv
				(chc & ((SBYTE)0xC0)) != 0x80)
			{
				goto BadLongCode;
			}

			chc &= 0x3F;

			// start a new long code
			if ((ch & 0x20) != 0)
			{

				// fold the first two bytes together
				chc |= (ch & 0x0F) << 6;

				if ((ch & 0x10) != 0)
				{
					// 4 byte encoding - surrogate
					ch = *pSrc;
					if (
						// check that bit 4 is zero, the non-shortest form of surrogate
						// and the valid surrogate range 0x000000 - 0x10FFFF at the same time
						!CHAR_IN_RANGE((chc >> 4), 0x01, 0x10) ||
						// we are expecting to see trailing bytes like 10vvvvvv
						(ch & ((SBYTE)0xC0)) != 0x80 )
					{
						goto BadLongCode;
					}

					chc = (chc << 6) | (ch & 0x3F);

					ch = *(pSrc+1);
					// we are expecting to see trailing bytes like 10vvvvvv
					if ((ch & ((SBYTE)0xC0)) != 0x80)
					{
						goto BadLongCode;
					}
					pSrc += 2;

					ch = (chc << 6) | (ch & 0x3F);

					*pTarget = (UCHAR)( ((ch >> 10) & 0x7FF) +
						((short)(CharUnicodeInfo::W_HIGH_SURROGATE_START - (0x10000 >> 10))) );
					pTarget++;

					ch = (ch & 0x3FF) +
						((short)(CharUnicodeInfo::W_LOW_SURROGATE_START));

					// extra byte, we're already planning 2 chars for 2 of these bytes,
					// but the big loop is testing the target against pStop, so we need
					// to subtract 2 more or we risk overrunning the input.  Subtract
					// one here and one below.
					pStop--;
				}
				else {
					// 3 byte encoding
					ch = *pSrc;
					if (
						// check for non-shortest form of 3 byte seq
						(chc & (0x1F << 5)) == 0 ||
						// Can't have surrogates here.
						(chc & (0xF800 >> 6) ) == (0xD800 >> 6) ||
						// we are expecting to see trailing bytes like 10vvvvvv
						(ch & ((SBYTE)0xC0)) != 0x80 )
					{
						goto BadLongCode;
					}
					pSrc++;

					ch = (chc << 6) | (ch & 0x3F);

					// extra byte, we're only expecting 1 char for each of these 3 bytes,
					// but the loop is testing the target (not source) against pStop, so
					// we need to subtract 2 more or we risk overrunning the input.
					// Subtract 1 here and one more below
					pStop--;
				}
			}
			else {
				// 2 byte encoding

				ch &= 0x1F;

				// check for non-shortest form
				if (ch <= 1)
				{
					goto BadLongCode;
				}
				ch = (ch << 6) | chc;
			}

			*pTarget = (UCHAR)ch;
			pTarget++;

			// extra byte, we're only expecting 1 char for each of these 2 bytes,
			// but the loop is testing the target (not source) against pStop.
			// subtract an extra count from pStop so that we don't overrun the input.
			pStop--;
		}
#endif // FASTLOOP

		BFX_ASSERT(pTarget <= pAllocatedBufferEnd);	// pTarget <= pAllocatedBufferEnd

		// no pending bits at this point
		ch = 0;
		continue;

BadLongCode:
		pSrc -= 2;
		ch = 0;
		continue;
	}

	// May have a problem if we have to flush
	if (ch != 0)
	{
		// We were already adjusting for these, so need to unadjust
		nCharCount += (ch >> 30);
		if (pDecoder == NULL || pDecoder->IsFlushRequired())
		{
			// Have to do fallback for invalid bytes
			if (pFallback == NULL)
			{
				if (pDecoder == NULL)
					pFallback = m_pDecoderFallback->CreateFallbackBuffer();
				else
					pFallback = pDecoder->GetFallbackBuffer();
				pFallback->Initialize(pBytes, pAllocatedBufferEnd);
			}

			// This'll back us up the appropriate # of bytes if we didn't get anywhere
			if (!FallbackInvalidByteSequence(INOUT pSrc, ch, pFallback, INOUT pTarget))
			{
				BFX_ASSERT1(pSrc >= pBytes || pTarget == pChars, "Expected to throw or remain in byte buffer while flushing");

				// Run out of buffer space. Need to throw an exception?
				pFallback->ResetAll();
				BFX_ENSURE1(false, "Chars buffer overflow");
			}

			BFX_ASSERT(pSrc >= pBytes);	// Expected flushing invalid byte sequence to have remained within the byte array
			ch = 0;
		}
	}

	if (pDecoder != NULL)
	{
		UTF8Decoder* pUtf8Decoder = (UTF8Decoder*)pDecoder;

		// If we're storing flush data we expect all bits to be used or else
		// we're stuck in the middle of a conversion
		BFX_ASSERT1(!pDecoder->IsFlushRequired() || ch == 0, "Expected no must flush or no left over bits or no throw on overflow.");

		// Remember our leftover bits.
		pUtf8Decoder->m_bits = ch;

		// TODO: pDecoder->m_nBytesUsed = (int)(pSrc - pBytes);
	}

	// Shouldn't have anything in fallback buffer for GetChars

	return WCHAR_PTR_DIFF(pTarget, pChars);
}

// To simplify maintenance, the structure of GetByteCount and GetBytes should be
// kept the same as much as possible
int REFUTF8Encoding::GetByteCount(const UCHAR* pChars, int nCount) const
{
	// Validate the parameters.
	BFX_REQUIRE (pChars != NULL && "Null pointer disallowed.");
	BFX_REQUIRE (nCount >= 0 && "Non-negative number required.");

	BFX_ASSERT(pChars!=NULL);
	BFX_ASSERT(nCount >=0);

	const UCHAR *pSrc = pChars;
	const UCHAR *pEnd = pSrc+nCount;

	// Start by assuming we have as many as count
	int nByteCount = nCount;

	int ch = 0;
	bool bFallingBack = false;
	for (;;)
	{
		// SLOWLOOP: does all range checks, handles all special cases, but it is slow
		if (pSrc >= pEnd)
		{
			if (ch == 0)
			{
				// Unroll any fallback that happens at the end
				ch = bFallingBack ? '?' : 0;
				bFallingBack = false;
				if (ch > 0)
				{
					nByteCount++;
					goto ProcessChar;
				}
			}
			else
			{
				// Case of surrogates in the fallback.
				if (bFallingBack)
				{
					BFX_ASSERT(ch >= 0xD800 && ch <= 0xDBFF);	// expected high surrogate

					ch = '?';
					bFallingBack = false;
					nByteCount++;

					if (CharUnicodeInfo::IsLowSurrogate(ch))
					{
						ch = 0xfffd;
						nByteCount++;
						goto EncodeChar;
					}
					else if (ch > 0)
					{
						goto ProcessChar;
					}
					else
					{
						nByteCount--; // ignore last one.
						break;
					}
				}
			}

			if (ch <= 0)
			{
				break;
			}

			// attempt to encode the partial surrogate (will fallback or ignore it), it'll also subtract 1.
			nByteCount++;
			goto EncodeChar;
		}

		if (ch > 0)
		{
			BFX_ASSERT(ch >= 0xD800 && ch <= 0xDBFF);	// expected high surrogate

			// use separate helper variables for local contexts so that the jit optimizations
			// won't get confused about the variable lifetimes
			int cha = *pSrc;

			// count the pending surrogate
			nByteCount++;

			// In previous byte, we encountered a high surrogate, so we are expecting a low surrogate here.
			if (CharUnicodeInfo::IsLowSurrogate(cha))
			{
				// Don't need a real # because we're just counting, anything > 0x7ff ('cept surrogate) will do.
				ch = 0xfffd;
				//                        ch = cha + (ch << 10) +
				//                            (0x10000
				//                            - CharUnicodeInfo.LOW_SURROGATE_START
				//                            - (CharUnicodeInfo.HIGH_SURROGATE_START << 10) );

				// Use this next char
				pSrc++;
			}
			// else ch is still high surrogate and encoding will fail (so don't add count)

			// attempt to encode the surrogate or partial surrogate
			goto EncodeChar;
		}

		// If we've used a fallback, then we have to check for it
		ch = bFallingBack ? '?' : 0;
		bFallingBack = false;
		if (ch > 0)
		{
			// We have an extra byte we weren't expecting.
			nByteCount++;
			goto ProcessChar;
		}

		// read next char. The JIT optimization seems to be getting confused when
		// compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
		ch = *pSrc;
		pSrc++;

ProcessChar:
		if (CharUnicodeInfo::IsHighSurrogate(ch))
		{
			// we will count this surrogate next time around
			nByteCount--;
			continue;
		}
		// either good char or partial surrogate

EncodeChar:
		// throw exception on partial surrogate if necessary
		if (CharUnicodeInfo::IsSurrogate(ch))
		{
			// Lone surrogates aren't allowed

			// Do our fallback.  Actually we already know its a mixed up surrogate,
			// so the ref pSrc isn't gonna do anything.
			pSrc ++;
			bFallingBack = true;

			// Ignore it if we don't throw (we had preallocated this ch)
			nByteCount--;
			ch = 0;
			continue;
		}

		// Count them
		if (ch > 0x7F)
		{
			if (ch > 0x7FF)
			{
				// the extra surrogate byte was compensated by the second surrogate character
				// (2 surrogates make 4 bytes.  We've already counted 2 bytes, 1 per char)
				nByteCount++;
			}
			nByteCount++;
		}

#ifdef FASTLOOP
		BFX_ASSERT(!bFallingBack);

		int nAvailableChars = WCHAR_PTR_DIFF(pEnd, pSrc);

		// don't fall into the fast decoding loop if we don't have enough characters
		if (nAvailableChars <= 13)
		{
			// try to get over the remainder of the ascii characters fast though
			const UCHAR* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered
			while (pSrc < pLocalEnd)
			{
				ch = *pSrc;
				pSrc++;
				if (ch > 0x7F)
					goto ProcessChar;
			}

			// we are done
			break;
		}


		// To compute the upper bound, assume that all characters are ASCII characters at this point,
		//  the boundary will be decreased for every non-ASCII character we encounter
		// Also, we need 3 + 4 chars reserve for the unrolled ansi decoding loop and for decoding of surrogates
		const UCHAR *pStop = pSrc + nAvailableChars - (3 + 4);

		while (pSrc < pStop)
		{
			ch = *pSrc;
			pSrc++;

			if (ch > 0x7F)                                                  // Not ASCII
			{
				if (ch > 0x7FF)                                             // Not 2 Byte
				{
					if ((ch & 0xF800) == 0xD800)                            // See if its a Surrogate
						goto LongCode;
					nByteCount++;
				}
				nByteCount ++;
			}

			// get pSrc aligned
			if ((((long)pSrc) & 0x2) != 0)
			{
				ch = *pSrc;
				pSrc++;
				if (ch > 0x7F)                                              // Not ASCII
				{
					if (ch > 0x7FF)                                         // Not 2 Byte
					{
						if ((ch & 0xF800) == 0xD800)                        // See if its a Surrogate
							goto LongCode;
						nByteCount++;
					}
					nByteCount ++;
				}
			}

			// Run 2 * 4 characters at a time!
			while (pSrc < pStop)
			{
				ch = *(int*)pSrc;
				int chc = *(int*)(pSrc+2);
				if (((ch | chc) & (int)0xFF80FF80) != 0)         // See if not ASCII
				{
					if (((ch | chc) & ((int)0xF800F800)) != 0)     // See if not 2 Byte
					{
						goto LongCodeWithMask;
					}


					if ((ch & ((int)0xFF800000)) != 0)             // Actually 0x07800780 is all we care about (4 bits)
						nByteCount++;
					if ((ch & ((int)0xFF80)) != 0)
						nByteCount++;
					if ((chc & ((int)0xFF800000)) != 0)
						nByteCount++;
					if ((chc & ((int)0xFF80)) != 0)
						nByteCount++;
				}
				pSrc += 4;

				ch = *(int*)pSrc;
				chc = *(int*)(pSrc+2);
				if (((ch | chc) & ((int)0xFF80FF80)) != 0)         // See if not ASCII
				{
					if (((ch | chc) & ((int)0xF800F800)) != 0)     // See if not 2 Byte
					{
						goto LongCodeWithMask;
					}

					if ((ch & ((int)0xFF800000)) != 0)
						nByteCount++;
					if ((ch & ((int)0xFF80)) != 0)
						nByteCount++;
					if ((chc & ((int)0xFF800000)) != 0)
						nByteCount++;
					if ((chc & ((int)0xFF80)) != 0)
						nByteCount++;
				}
				pSrc += 4;
			}
			break;

LongCodeWithMask:
#ifdef BIGENDIAN
			// be careful about the sign extension
			ch = (int)(((UINT)ch) >> 16);
#else // BIGENDIAN
			ch = (UCHAR)ch;
#endif // BIGENDIAN
			pSrc++;

			if (ch <= 0x7F)
			{
				continue;
			}

LongCode:
			// use separate helper variables for slow and fast loop so that the jit optimizations
			// won't get confused about the variable lifetimes
			if (ch > 0x7FF)
			{
				if (CharUnicodeInfo::IsSurrogate(ch))
				{
					// 4 byte encoding - high surrogate + low surrogate

					int chd = *pSrc;
					if (
						// !IsHighSurrogate(ch) // low without high -> bad
						ch > CharUnicodeInfo::W_HIGH_SURROGATE_END ||
						// !IsLowSurrogate(chd) // high not followed by low -> bad
						!CharUnicodeInfo::IsLowSurrogate(chd) )
					{
						// Back up and drop out to slow loop to figure out error
						pSrc--;
						break;
					}
					pSrc++;

					// nByteCount - this byte is compensated by the second surrogate character
				}
				nByteCount++;
			}
			nByteCount++;

			// nByteCount - the last byte is already included
		}
#endif // FASTLOOP

		// no pending char at this point
		ch = 0;
	}

	return nByteCount;
}

// Our workhorse
// Note:  We ignore mismatched surrogates, unless the exception flag is set in which case we throw
int REFUTF8Encoding::GetBytes(const UCHAR* pChars, int nCharCount, OUT BYTE* pBytes, int nByteCount) const
{
	// Validate the parameters.
	BFX_REQUIRE ((pChars != NULL && pBytes != NULL) && "Null reference of argument disallowed.");
	BFX_REQUIRE ((nCharCount >= 0 && nByteCount >= 0) && "Non-negative number required.");

	BFX_ASSERT(pChars != NULL);
	BFX_ASSERT(nByteCount >=0);
	BFX_ASSERT(nCharCount >=0);
	BFX_ASSERT(pBytes!=NULL);

	const UCHAR *pSrc = pChars;
	BYTE *pTarget = pBytes;

	const UCHAR *pEnd = pSrc+nCharCount;
	BYTE *pAllocatedBufferEnd = pTarget+nByteCount;

	int ch = 0;
	bool bFallingBack = false;
	// assume that JIT will enregister pSrc, pTarget and ch

	for (;;)
	{
		// SLOWLOOP: does all range checks, handles all special cases, but it is slow

		if (pSrc >= pEnd)
		{
			if (ch == 0)
			{
				// Check if falling back
				ch = bFallingBack ? '?' : 0;
				bFallingBack = false;
				if (ch > 0)
				{
					goto ProcessChar;
				}
			}

			// attempt to encode the partial surrogate (will fail or ignore)
			if (ch > 0)
				goto EncodeChar;

			// We're done
			break;
		}

		if (ch > 0)
		{
			// We have a high surrogate left over from a previous loop.
			BFX_ASSERT(ch >= 0xD800 && ch <= 0xDBFF);	// expected high surrogate

			// use separate helper variables for local contexts so that the jit optimizations
			// won't get confused about the variable lifetimes
			int cha = *pSrc;

			// In previous byte, we encountered a high surrogate, so we are expecting a low surrogate here.
			if (CharUnicodeInfo::IsLowSurrogate(cha))
			{
				ch = cha + (ch << 10) +
					(0x10000
					- CharUnicodeInfo::W_LOW_SURROGATE_START
					- (CharUnicodeInfo::W_HIGH_SURROGATE_START << 10) );

				pSrc++;
			}
			// else ch is still high surrogate and encoding will fail

			// attempt to encode the surrogate or partial surrogate
			goto EncodeChar;
		}

		// If we've used a fallback, then we have to check for it
		ch = bFallingBack ? '?' : 0;
		bFallingBack = false;
		if (ch > 0)
			goto ProcessChar;

		// read next char. The JIT optimization seems to be getting confused when
		// compiling "ch = *pSrc++;", so rather use "ch = *pSrc; pSrc++;" instead
		ch = *pSrc;
		pSrc++;

ProcessChar:
		if (CharUnicodeInfo::IsHighSurrogate(ch))
		{
			continue;
		}
		// either good char or partial surrogate

EncodeChar:
		// throw exception on partial surrogate if necessary
		if (CharUnicodeInfo::IsSurrogate(ch))
		{
			// Lone surrogates aren't allowed, we have to do fallback for them

			// Do our fallback.  Actually we already know its a mixed up surrogate,
			// so the ref pSrc isn't gonna do anything.
			bFallingBack = true;
			pSrc ++;

			// Ignore it if we don't throw
			ch = 0;
			continue;
		}

		// Count bytes needed
		int bytesNeeded = 1;
		if (ch > 0x7F)
		{
			if (ch > 0x7FF)
			{
				if (ch > 0xFFFF)
				{
					bytesNeeded++;  // 4 bytes (surrogate pair)
				}
				bytesNeeded++;      // 3 bytes (800-FFFF)
			}
			bytesNeeded++;          // 2 bytes (80-7FF)
		}

		if (pTarget > pAllocatedBufferEnd - bytesNeeded)
		{
			BFX_ASSERT(!bFallingBack);

			pSrc--;                                     // Didn't use this char
			if (ch > 0xFFFF)
				pSrc--;                                 // Was surrogate, didn't use 2nd part either

			// Left over surrogate from last time will cause pSrc == pChars, so we'll throw
			BFX_ASSERT(pSrc >= pChars || pTarget == pBytes);	// Expected pSrc to be within buffer or to throw with insufficient room.");

			// Throw maybe (if no bytes written)
			BFX_ENSURE(pTarget != pBytes && "The output byte buffer is too small to contain the encoded data");

			ch = 0;                                         // Nothing left over (we backed up to start of pair if supplimentary)
			break;
		}

		if (ch <= 0x7F)
		{
			*pTarget = (BYTE)ch;
		}
		else {
			// multi-bytes encoding
			int chb;
			if (ch <= 0x7FF)
			{
				// 2 byte encoding
				chb = (BYTE)(((SBYTE)0xC0) | (ch >> 6));
			}
			else
			{
				if (ch <= 0xFFFF)
				{
					chb = (BYTE)(((SBYTE)0xE0) | (ch >> 12));
				}
				else
				{
					*pTarget = (BYTE)(((SBYTE)0xF0) | (ch >> 18));
					pTarget++;

					chb = ((SBYTE)0x80) | ((ch >> 12) & 0x3F);
				}
				*pTarget = (BYTE)chb;
				pTarget++;

				chb = ((SBYTE)0x80) | ((ch >> 6) & 0x3F);
			}
			*pTarget = (BYTE)chb;
			pTarget++;

			*pTarget = (BYTE)(((SBYTE)0x80) | (ch & 0x3F));
		}
		pTarget++;

#ifdef FASTLOOP

		// If still have fallback don't do fast loop
		BFX_ASSERT(!bFallingBack);

		int nAvailableChars = WCHAR_PTR_DIFF(pEnd, pSrc);
		int nAvailableBytes = BYTE_PTR_DIFF(pAllocatedBufferEnd, pTarget);

		// don't fall into the fast decoding loop if we don't have enough characters
		// Note that if we don't have enough bytes, pStop will prevent us from entering the fast loop.
		if (nAvailableChars <= 13)
		{
			// we are hoping for 1 byte per char
			if (nAvailableBytes < nAvailableChars)
			{
				// not enough output room.  no pending bits at this point
				ch = 0;
				continue;
			}

			// try to get over the remainder of the ascii characters fast though
			const UCHAR* pLocalEnd = pEnd; // hint to get pLocalEnd enregistered
			while (pSrc < pLocalEnd)
			{
				ch = *pSrc;
				pSrc++;

				// Not ASCII, need more than 1 byte per char
				if (ch > 0x7F)
					goto ProcessChar;

				*pTarget = (BYTE)ch;
				pTarget++;
			}
			// we are done, let ch be 0 to clear encoder
			ch = 0;
			break;
		}

		// we need at least 1 byte per character, but Convert might allow us to convert
		// only part of the input, so try as much as we can.  Reduce nCharCount if necessary
		if (nAvailableBytes < nAvailableChars)
		{
			nAvailableChars = nAvailableBytes;
		}

		// FASTLOOP:
		// - optimistic range checks
		// - fallbacks to the slow loop for all special cases, exception throwing, etc.

		// To compute the upper bound, assume that all characters are ASCII characters at this point,
		//  the boundary will be decreased for every non-ASCII character we encounter
		// Also, we need 5 chars reserve for the unrolled ansi decoding loop and for decoding of surrogates
		// If there aren't enough bytes for the output, then pStop will be <= pSrc and will bypass the loop.
		const UCHAR *pStop = pSrc + nAvailableChars - 5;

		while (pSrc < pStop)
		{
			ch = *pSrc;
			pSrc++;

			if (ch > 0x7F)
			{
				goto LongCode;
			}
			*pTarget = (BYTE)ch;
			pTarget++;

			// get pSrc aligned
			if ((((long)pSrc) & 0x2) != 0)
			{
				ch = *pSrc;
				pSrc++;
				if (ch > 0x7F)
				{
					goto LongCode;
				}
				*pTarget = (BYTE)ch;
				pTarget++;
			}

			// Run 4 characters at a time!
			while (pSrc < pStop)
			{
				ch = *(int*)pSrc;
				int chc = *(int*)(pSrc+2);
				if (((ch | chc) & ((int)0xFF80FF80)) != 0)
				{
					goto LongCodeWithMask;
				}

#ifdef BIGENDIAN
				*pTarget = (BYTE)(ch>>16);
				*(pTarget+1) = (BYTE)ch;
				pSrc += 4;
				*(pTarget+2) = (BYTE)(chc>>16);
				*(pTarget+3) = (BYTE)chc;
				pTarget += 4;
#else // BIGENDIAN
				*pTarget = (BYTE)ch;
				*(pTarget+1) = (BYTE)(ch>>16);
				pSrc += 4;
				*(pTarget+2) = (BYTE)chc;
				*(pTarget+3) = (BYTE)(chc>>16);
				pTarget += 4;
#endif // BIGENDIAN
			}
			continue;

LongCodeWithMask:
#ifdef BIGENDIAN
			// be careful about the sign extension
			ch = (int)(((UINT)ch) >> 16);
#else // BIGENDIAN
			ch = (UCHAR)ch;
#endif // BIGENDIAN
			pSrc++;

			if (ch > 0x7F)
			{
				goto LongCode;
			}
			*pTarget = (BYTE)ch;
			pTarget++;
			continue;

LongCode:
			// use separate helper variables for slow and fast loop so that the jit optimizations
			// won't get confused about the variable lifetimes
			int chd;
			if (ch <= 0x7FF)
			{
				// 2 byte encoding
				chd = ((SBYTE)0xC0) | (ch >> 6);
			}
			else
			{
				if (!CharUnicodeInfo::IsSurrogate(ch))
				{
					// 3 byte encoding
					chd = ((SBYTE)0xE0) | (ch >> 12);
				}
				else
				{
					// 4 byte encoding - high surrogate + low surrogate
					// if (!IsHighSurrogate(ch))
					if (ch > CharUnicodeInfo::W_HIGH_SURROGATE_END)
					{
						// low without high -> bad, try again in slow loop
						pSrc -= 1;
						break;
					}

					chd = *pSrc;
					pSrc++;

					if (!CharUnicodeInfo::IsLowSurrogate(chd))
					{
						// high not followed by low -> bad, try again in slow loop
						pSrc -= 2;
						break;
					}

					ch = chd + (ch << 10) +
						(0x10000
						- CharUnicodeInfo::W_LOW_SURROGATE_START
						- (CharUnicodeInfo::W_HIGH_SURROGATE_START << 10) );

					*pTarget = (BYTE)(((SBYTE)0xF0) | (ch >> 18));
					// pStop - this byte is compensated by the second surrogate character
					// 2 input chars require 4 output bytes.  2 have been anticipated already
					// and 2 more will be accounted for by the 2 pStop-- calls below.
					pTarget++;

					chd = ((SBYTE)0x80) | ((ch >> 12) & 0x3F);
				}
				*pTarget = (BYTE)chd;
				pStop--;                    // 3 byte sequence for 1 char, so need pStop-- and the one below too.
				pTarget++;

				chd = ((SBYTE)0x80) | ((ch >> 6) & 0x3F);
			}
			*pTarget = (BYTE)chd;
			pStop--;                        // 2 byte sequence for 1 char so need pStop--.
			pTarget++;

			*pTarget = (BYTE)((SBYTE)0x80) | (ch & 0x3F);
			// pStop - this byte is already included
			pTarget++;
		}

		BFX_ASSERT(pTarget <= pAllocatedBufferEnd);
#endif // FASTLOOP

		// no pending char at this point
		ch = 0;
	}

	return (int)(pTarget - pBytes);
}

// During GetChars we had an invalid byte sequence
// pSrc is backed up to the start of the bad sequence if we didn't have room to fall it back.
// Otherwise pSrc remains wher it is.
bool REFUTF8Encoding::FallbackInvalidByteSequence(INOUT const BYTE*& pSrc, int ch, REFDecoderFallbackBuffer* pFallbackBuffer, INOUT UCHAR*& pTarget) const
{
	// Get our byte[]
	const BYTE *pStart = pSrc;
	SequenceT<BYTE> bytesUnknown = GetBytesUnknown(INOUT pStart, ch);

	// Do the actual fallback
	if (!pFallbackBuffer->Fallback(bytesUnknown, pSrc, INOUT pTarget))
	{
		// Oops, it failed, back up to pStart
		pSrc = pStart;
		return false;
	}

	// It worked
	return true;
}

// During GetCharCount we had an invalid byte sequence
// pSrc is used to find the index that points to the invalid bytes,
// however the byte[] contains the fallback bytes (in case the index is -1)
int REFUTF8Encoding::FallbackInvalidByteSequence(INOUT const BYTE*& pSrc, int ch, REFDecoderFallbackBuffer* pFallbackBuffer) const
{
	// Get our byte[]
	SequenceT<BYTE> bytesUnknown = GetBytesUnknown(INOUT pSrc, ch);

	// Do the actual fallback
	int nCount = pFallbackBuffer->Fallback(bytesUnknown, pSrc);

	// # of fallback chars expected.
	// Note that we only get here for "long" sequences, and have already unreserved
	// the count that we prereserved for the input bytes
	return nCount;
}

// Note that some of these bytes may have come from a previous fallback, so we cannot
// just decrement the pointer and use the values we read.  In those cases we have to regenerate the original values.
SequenceT<BYTE> REFUTF8Encoding::GetBytesUnknown(INOUT const BYTE*& pSrc, int ch) const
{
	SequenceT<BYTE> result;
	const BYTE* pStart = pSrc;

	// Get our byte array.
	BYTE* pBuf = result.GetBuffer(3);	// 3 bytes is big enough.

	// See if it was a plain char
	// (have to check >= 0 because we have all sorts of wierd bit flags)
	if (ch < 0x100 && ch >= 0)
	{
		pSrc--;
		pBuf[0] = (BYTE)ch;
	}
	// See if its an unfinished 2 byte sequence
	else if ((ch & (SUPPLIMENTARY_SEQ | THREE_BYTE_SEQ)) == 0)
	{
		pBuf[0] = (BYTE)((ch & 0x1F) | 0xC0);
	}
	// So now we're either 2nd byte of 3 or 4 byte sequence or
	// we hit a non-trail byte or we ran out of space for 3rd byte of 4 byte sequence
	// 1st check if its a 4 byte sequence
	else if ((ch & SUPPLIMENTARY_SEQ) != 0)
	{
		//  3rd byte of 4 byte sequence?
		if ((ch & (FINAL_BYTE >> 6)) != 0)
		{
			// 3rd byte of 4 byte sequence
			pSrc-=3;
			pBuf[0] = (BYTE)(((ch >> 12) & 0x07) | 0xF0);
			pBuf[1] = (BYTE)(((ch >> 6) & 0x3F) | 0x80);
			pBuf[2] = (BYTE)(((ch) & 0x3F) | 0x80);
		}
		else if ((ch & (FINAL_BYTE >> 12)) != 0)
		{
			// 2nd byte of a 4 byte sequence
			pSrc-=2;
			pBuf[0] = (BYTE)(((ch >> 6) & 0x07) | 0xF0);
			pBuf[1] = (BYTE)(((ch) & 0x3F) | 0x80);
		}
		else
		{
			// 4th byte of a 4 byte sequence
			pSrc--;
			pBuf[0] = (BYTE)(((ch) & 0x07) | 0xF0);
		}
	}
	else
	{
		// 2nd byte of 3 byte sequence?
		if ((ch & (FINAL_BYTE >> 6)) != 0)
		{
			// So its 2nd byte of a 3 byte sequence
			pSrc-=2;
			pBuf[0] = (BYTE)(((ch >> 6) & 0x0F) | 0xE0);
			pBuf[1] = (BYTE)(((ch) & 0x3F) | 0x80);
		}
		else
		{
			// 1st byte of a 3 byte sequence
			pSrc--;
			pBuf[0] = (BYTE)(((ch) & 0x0F) | 0xE0);
		}
	}

	BFX_ASSERT1((pStart - pSrc) <= 3, "Buffer overflow.");
	result.ReleaseBuffer(pStart - pSrc);

	return result;
}

// Returns a Decoder object for this encoding. The returned object can be used to decode a sequence of bytes into a sequence of characters.
// Contrary to the GetChars family of methods, a Decoder can convert partial sequences of bytes into partial sequences of characters
// by maintaining the appropriate state between the conversions.
REFDecoder* REFUTF8Encoding::GetDecoder() const
{
	REFDecoder* pDecoder = new UTF8Decoder(this);
	pDecoder->Autorelease();
	return pDecoder;
}

// Initializes the UTF-8 decoder.
REFUTF8Encoding::UTF8Decoder::UTF8Decoder(const REFUTF8Encoding* pEncoding)
	: REFDecoder(pEncoding), m_bits(0)
{
}

REFUTF8Encoding::UTF8Decoder::~UTF8Decoder()
{
}

void REFUTF8Encoding::UTF8Decoder::Reset()
{
	m_bits = 0;
	REFDecoder::Reset();
}


}	//	namespace BFX
